package com.gitee.wsl.doc.prosemirror.state.selection

import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
import com.gitee.wsl.doc.prosemirror.model.node.Node
import com.gitee.wsl.doc.prosemirror.state.Transaction
import com.gitee.wsl.doc.prosemirror.state.bookmark.AllBookmark
import com.gitee.wsl.doc.prosemirror.transform.ext.delete
import com.gitee.wsl.doc.prosemirror.transform.map.Mappable
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

// A selection type that represents selecting the whole document (which can not necessarily be
// expressed with a text selection, when there are for example leaf block nodes at the start or end
// of the document).
class AllSelection(
    // Create an all-selection over the given document.
    doc: Node
) : Selection(doc.resolve(0), doc.resolve(doc.content.size)) {

    override fun replace(tr: Transaction, content: Slice) {
        if (content == Slice.empty) {
            tr.delete(0, tr.doc.content.size)
            val sel = atStart(tr.doc)
            if (sel != tr.selection) tr.setSelection(sel)
        } else {
            super.replace(tr, content)
        }
    }

    override fun toJSON() = buildJsonObject {
        put("type", "all")
    }

    override fun map(doc: Node, mapping: Mappable) = AllSelection(doc)

    fun eq(other: Selection) = other is AllSelection

    override fun getBookmark() = AllBookmark

    companion object : SelectionClass {

        init {
            jsonID("all", this)
        }

        override fun fromJSON(doc: Node, json: JsonObject): Selection = AllSelection(doc)
    }
}